/***********************************
* Name: MethodInterCodeGen.java
* Date: Aug 20, 2010
* @author martin
* Description:
***********************************/

package interCodeGen;

import decaf.*;
import goldengine.java.*;
import java.util.LinkedList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;

public class MethodInterCodeGen {

    
    public  Method method;
    public  Scope scope;
    public  DecafParser parser;
    public  LinkedList<Cod3Dir> codigo = new LinkedList<Cod3Dir>();
    public  LinkedHashMap<String,String> hashTemp = new LinkedHashMap<String,String>();

    private Scope actual_ambit;
    private Reduction methodDecaration_red;
    private int label_cont = 0;
    private int temp_cont = 1;
    private LinkedList<String> temporales = new LinkedList<String>();
    private LinkedList<String> temporales_location = new LinkedList<String>();
    private boolean primer_bloque = false;
    private int inicio_dir_temp = 0;

    /*****************************************
     * constructor
     *****************************************/
    public MethodInterCodeGen(Method met, Scope scope, Reduction red, DecafParser parser){

        this.method = met;
        this.scope = scope;
        this.actual_ambit = scope;
        this.actual_ambit.resetGetKid();
        this.methodDecaration_red = red;
        this.parser = parser;
        
    }

    /*****************************************
     * getCode
     * @return the code from the method
     *****************************************/
    public LinkedList<Cod3Dir> getCode(){
        return this.codigo;
    }

    /*****************************************
     * newLabel
     * @return String with the form L__main$0_1
     *****************************************/
    public String newLabel(){
        //L_main$0_1
        return "L_"+this.method.getSubname()+"_"+(label_cont++);
    }

    /*****************************************
     * getLabelEnd
     * @return String with the form L_main$0_1
     *****************************************/
    public String getLabelEnd(){
        //L__main$0__end
        return "L_"+this.method.getSubname()+"_end";
    }


    /*****************************************
     * getTemporal
     * @return String with the form t$_0
     *****************************************/
    private String getTemporal(){
        if(temporales.isEmpty()){
            return "t$_"+(this.temp_cont++);
        }
        return temporales.pop();
    }

    /*****************************************
     * isTemporal
     * @return String with the form t$_0
     *****************************************/
    public static boolean isTemporal(String temp){
        return temp.startsWith("t$_");
    }

    /*****************************************
     * liberarTemporal
     * @param String with temporal to liberate
     *****************************************/
    private void liberarTemporal(String temp){
        if(isTemporal(temp)){
            this.temporales.push(temp);
            
            Collections.sort(temporales,new Comparator<String>(){

                public int compare(String o1, String o2) {

                    int a1 = Integer.parseInt(o1.substring(3));
                    int a2 = Integer.parseInt(o2.substring(3));
                    return a1-a2;
                }

            });
        }
    }


    /*****************************************
     * generate
     *****************************************/
    public void generate(){
        //<methodDeclaration> ::= <Type> id '(' <opt_parameter> ')' <block>
        String name = this.method.getSubname();

        this.addToCode(new InterComentario("*******************************************"));
        this.addToCode(new InterComentario("Method: "+name));
        this.addToCode(new InterComentario("Return type: "+this.method.getRet().getType_name()));

        int suma=0;

        for(decaf.Symbol a : this.parser.getSymbolTable().getAllSymbolInScopeAndKids(scope)){
            String param = "";
            if(a.getType().isParam()){
                param = "param: ";
            }
            String [] b = this.getDesplazamientoSimple(a,parser,this.scope);
            this.addToCode(new InterComentario(param+a.getId()+" = "+b[0]+"["+b[1]+"]"));

            suma += a.getType().getType_length();
        }
        this.inicio_dir_temp = suma;
        
        this.addToCode(new InterComentario("*******************************************"));
        this.addToCode(new InterPlane(name+" proc near"));

        primer_bloque = true;
        this.genCodeStatement((Reduction)methodDecaration_red.getToken(5).getData());


        //Etiqueta final
        //  ret
        //nombre endp
        this.addToCode(new InterEtiqueta(this.getLabelEnd()));
        this.addToCode(new InterPlane("\tret"));
        this.addToCode(new InterPlane(name+" endp"));
        this.addToCode(new InterComentario("*******************************************\n\n"));



        //agregar las direcciones de las temporales
        int cont = this.parser.getSymbolTable().getAllSymbolInScopeAndKids(scope).size();
        int tam_ind = Type.getBasicTamano("int");

        for(int i = 1; i < this.temp_cont; i++){
            this.codigo.add(cont+i+2,new InterComentario(("t$_"+i)+" = "+"stack["+(i*tam_ind-tam_ind+this.inicio_dir_temp)+"]"));
            hashTemp.put(("t$_"+i), "stack["+(i*tam_ind-tam_ind+this.inicio_dir_temp)+"]");
        }

        int param_len=0, dato_loc_len=0;

        for(decaf.Symbol a : this.parser.getSymbolTable().getAllSymbolInScopeAndKids(scope)){
            if(a.getType().isParam()){
                param_len+=a.getType().getType_length();
            }else{
                dato_loc_len+=a.getType().getType_length();
            }
        }

        this.method.tam_parametros = param_len;
        this.method.tam_datos_locales = dato_loc_len;
        this.method.tam_temporales = tam_ind * hashTemp.size();
        this.method.tam_dir_ret = 2;//TODO ver tamaño de la dirección de retorno
        this.method.tam_val_ret = this.method.getRet().getType_length();

    }

    /*****************************************
     * addToCode
     * @param cod to add
     * @return void
     *****************************************/
    private void addToCode(Cod3Dir cod){
        this.codigo.add(cod);
    }

    /*****************************************
     * genCode
     * @param reduction
     * @return String
     *****************************************/
    private void genCodeStatement(Reduction reduction){

        InterEtiqueta L1;
        InterEtiqueta L2;
        String t1,t2;
        //boolean linea = true;

        switch(reduction.getParentRule().getTableIndex())
        {
            case DecafParser.RuleConstants.RULE_BLOCK_LBRACE_RBRACE:
                //#########################################################################################################
                //<block> ::= '{' <kleene_varDeclaration> <kleene_statement> '}'

                boolean regresar = false;
                if(!primer_bloque){
                    //meterser a un hijo
                    this.actual_ambit = this.actual_ambit.getKid();
                    regresar = true;
                    //System.out.println("entra a nuevo ámbito: "+this.actual_ambit.getName());
                }else{
                    primer_bloque = false;
                }
                
                this.genCodeStatement((Reduction)reduction.getToken(2).getData());

                if(regresar){
                    //System.out.println("sale del ámbito: "+this.actual_ambit.getName());
                    this.actual_ambit = this.actual_ambit.getPrev_scope();
                    //System.out.println("regresa al ámbito: "+this.actual_ambit.getName());
                }

                break;
            case DecafParser.RuleConstants.RULE_KLEENE_STATEMENT:
                //#########################################################################################################
                //<kleene_statement> ::= <statement> <kleene_statement>
                this.genCodeStatement((Reduction)reduction.getToken(0).getData());
                this.genCodeStatement((Reduction)reduction.getToken(1).getData());
                break;
            case DecafParser.RuleConstants.RULE_KLEENE_STATEMENT2:
                //#########################################################################################################
                //<kleene_statement> ::=
                break;
            case DecafParser.RuleConstants.RULE_STATEMENT:
                //#########################################################################################################
                //<statement> ::= <block>
                this.genCodeStatement((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_STATEMENT2: case DecafParser.RuleConstants.RULE_STATEMENT3: case DecafParser.RuleConstants.RULE_STATEMENT_SEMI:
            case DecafParser.RuleConstants.RULE_STATEMENT_SEMI2:  case DecafParser.RuleConstants.RULE_STATEMENT_SEMI3:
                //#########################################################################################################
                //<statement> ::= <selection>
                //<statement> ::= <iteration>
                //<statement> ::= <return> ';'
                //<statement> ::= <assign> ';'
                //<statement> ::= <opt_expression> ';'
                this.genCodeStatement((Reduction)reduction.getToken(0).getData());
                break;

            case DecafParser.RuleConstants.RULE_SELECTION_IF_LPARAN_RPARAN:
                //#########################################################################################################
                //<selection> ::= if '(' <expression> ')' <block> <opt_else_block>
                //<opt_else_block> ::= else <block>
                //<opt_else_block> ::=

                Reduction opt_else_block = (Reduction)reduction.getToken(5).getData();

                if(  opt_else_block.getTokenCount() == 0 ){

                    /*-------------------------------------------------------------------------
                    if ( <exp> ) <block1>
                    Código:
                            cod(<exp>) -> temp1
                            if temp1 == 0 goto L1
                            cod(<block1>)
                    L1:
                    -------------------------------------------------------------------------*/

                    this.addToCode(new InterComentario(" if(<exp>) <block1> ",false,'#',40));

                    L1 = new InterEtiqueta(this.newLabel());

                    t1 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                    this.addToCode(new InterCondicional(t1,"==",0+"", L1.getEtiqueta()));

                    this.genCodeStatement((Reduction)reduction.getToken(4).getData());

                    this.addToCode(L1);

                    this.addToCode(new InterComentario("",false,'#',40));

                    this.liberarTemporal(t1);

                    break;
                }

                /*-------------------------------------------------------------------------
                if ( <exp> ) <block1> else <block2>
                Código:
                        cod(<exp>) -> temp1
                        if temp1 == 0 goto L1
                        cod(<block1>)
                        goto L2
                L1:
                        cod(<block2>)
                L2:
                -------------------------------------------------------------------------*/

                this.addToCode(new InterComentario(" if(<exp>) <block1> else <block2> ",false,'#',40));

                L1 = new InterEtiqueta(this.newLabel());
                L2 = new InterEtiqueta(this.newLabel());

                t1 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                this.addToCode(new InterCondicional(t1,"==",0+"", L1.getEtiqueta()));

                this.addToCode(new InterComentario(" <block1> ",false,'#',40));

                this.genCodeStatement((Reduction)reduction.getToken(4).getData());

                this.addToCode(new InterSalto(L2.getEtiqueta()));

                this.addToCode(L1);

                this.addToCode(new InterComentario(" <block2> - else ",false,'#',40));

                this.genCodeStatement((Reduction)opt_else_block.getToken(1).getData());

                this.addToCode(L2);

                this.addToCode(new InterComentario("",false,'#',40));

                this.liberarTemporal(t1);

                break;
            case DecafParser.RuleConstants.RULE_ITERATION_WHILE_LPARAN_RPARAN:
                //#########################################################################################################
                //<iteration> ::= while '(' <expression> ')' <block>


                /*-------------------------------------------------------------------------
                while ( <exp> ) <block>

                Código:

                L1:
                        cod(<exp>) -> temp1
                        if temp1 == 0 goto L2
                        cod(<block1>)
                        goto L1:
                L2:
                -------------------------------------------------------------------------*/

                this.addToCode(new InterComentario(" while (<exp>) <block> ",false,'#',40));

                L1 = new InterEtiqueta(this.newLabel());
                L2 = new InterEtiqueta(this.newLabel());


                this.addToCode(L1);

                t1 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                this.addToCode(new InterCondicional(t1,"==",0+"", L2.getEtiqueta()));

                this.genCodeStatement((Reduction)reduction.getToken(4).getData());

                this.addToCode(new InterSalto(L1.getEtiqueta()));

                this.addToCode(L2);

                this.addToCode(new InterComentario("",false,'#',40));

                this.liberarTemporal(t1);
                
                break;
            case DecafParser.RuleConstants.RULE_RETURN_RETURN:
                //#########################################################################################################
                //<return> ::= return <opt_expression>
                //<opt_expression> ::= <expression> |
                Reduction opt_expression = (Reduction)reduction.getToken(1).getData();
                if(opt_expression.getTokenCount() == 0){

                    /*-------------------------------------------------------------------------
                    return  ;
                    Código:
                            goto L_metodo_end
                    -------------------------------------------------------------------------*/
                    this.addToCode(new InterSalto(this.getLabelEnd()));

                    break;
                }

                /*-------------------------------------------------------------------------
                return <exp> ;
                Código:
                        cod(<exp>)-> temp1
                        return temp1
                        goto L_metodo_end
                -------------------------------------------------------------------------*/

                t1 = this.genCodeExpression((Reduction)opt_expression.getToken(0).getData());

                this.addToCode(new InterReturn(t1));

                this.addToCode(new InterSalto(this.getLabelEnd()));

                this.liberarTemporal(t1);
                
                break;
            case DecafParser.RuleConstants.RULE_ASSIGN_EQ:
                //#########################################################################################################
                //<assign> ::= <location> '=' <expression>

                /*-------------------------------------------------------------------------
                <location>  =  <exp>
                Código:
                        cod(<exp>) -> temp1
                        cod(<location>) -> temp2
                        temp2 = temp1
                -------------------------------------------------------------------------*/
                
                this.addToCode(new InterComentario(" <assign> ",false,'-',40));

                t1 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                t2 = this.genCodeLocation((Reduction)reduction.getToken(0).getData());

                this.addToCode(new InterAsignacion(t2,t1));

                this.liberarTemporal(t1);

                this.addToCode(new InterComentario("",false,'-',40));
                
                break;
            case DecafParser.RuleConstants.RULE_OPT_EXPRESSION:
                //#########################################################################################################
                //<opt_expression> ::= <expression>
                
                /*-------------------------------------------------------------------------
                <exp> ;
                Código:
                        cod(<exp>)
                -------------------------------------------------------------------------*/

                t1 = this.genCodeExpression((Reduction)reduction.getToken(0).getData());

                this.liberarTemporal(t1);

                break;
        }

        

    }



    
    /*****************************************
     * genCodeExpression
     * @param reduction
     * @return String
     *****************************************/
    private String genCodeExpression(Reduction reduction){
        String retorno = "";

        String t1,t2,t3, operando;
        InterEtiqueta L1,L2,L3;

        switch(reduction.getParentRule().getTableIndex())
        {
            case DecafParser.RuleConstants.RULE_EXPRESSION:
                //#########################################################################################################
                //<expression> ::= <Rel Exp> <conditionalop> <expression>
                
                /*-------------------------------------------------------------------------
                <Rel Exp> <conditionalop> <exp1>
                Código:
                        //&& ||
                        cod(<rel exp>) -> t1
                        cod(<exp1>) -> t2
                        t3 = t1 AND|OR t2
                Resultado en: t3
                -------------------------------------------------------------------------*/

                operando = (String)((Reduction)reduction.getToken(1).getData()).getToken(0).getData();

                if(operando.equals("&&")){

                    operando = "and";

                }else if(operando.equals("||")){

                    operando = "or";
                }

                this.addToCode(new InterComentario(" <boolean exp> ("+operando+") ",true,'=',30));//=====

                t1 = this.genCodeExpression((Reduction)reduction.getToken(0).getData());

                t2 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                this.liberarTemporal(t1);
                this.liberarTemporal(t2);

                t3 = this.getTemporal();

                this.addToCode(new InterOperacionBinaria(t3,t1,operando,t2));
                
                retorno = t3;

                //this.liberarTemporal(t1);
                //this.liberarTemporal(t2);

                this.addToCode(new InterComentario("",true,'=',30));//===================================

                break;
            case DecafParser.RuleConstants.RULE_EXPRESSION2:
                //#########################################################################################################
                //<expression> ::= <Rel Exp>
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_RELEXP:
                //#########################################################################################################
                //<Rel Exp> ::= <Add Exp> <relop> <Rel Exp>

                /*-------------------------------------------------------------------------
                <Add Exp> <relop> <Rel exp1>
                Código:
                        //<= < > >= == !=
                        cod(<Add Exp>) -> t1
                        cod(<Rel exp1>) -> t2
                        if t1 <relop> t2 goto L1
                        t3 =0
                        goto L2
                L1:
                        t3=1
                L2:
                Resultado en: t3
                -------------------------------------------------------------------------*/

                L1 = new InterEtiqueta(this.newLabel());
                L2 = new InterEtiqueta(this.newLabel());

                t1 = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                t2 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                this.liberarTemporal(t1);
                this.liberarTemporal(t2);

                t3 = this.getTemporal();

                operando = (String)((Reduction)reduction.getToken(1).getData()).getToken(0).getData();

                this.addToCode(new InterCondicional(t1,operando,t2, L1.getEtiqueta()));

                this.addToCode(new InterAsignacion(t3,"0"));

                this.addToCode(new InterSalto(L2.getEtiqueta()));

                this.addToCode(L1);

                this.addToCode(new InterAsignacion(t3,"1"));

                this.addToCode(L2);

                retorno = t3;

                //this.liberarTemporal(t1);
                //this.liberarTemporal(t2);


                break;
            case DecafParser.RuleConstants.RULE_RELEXP2:
                //#########################################################################################################
                //<Rel Exp> ::= <Add Exp>
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_ADDEXP:
                //#########################################################################################################
                //<Add Exp> ::= <Mult Exp> <addop> <Add Exp>


                /*-------------------------------------------------------------------------
                <Mult Exp> <addop> <Add exp1>
                Código:
                        //+ -
                        cod(<Mult Exp>) -> t1
                        cod(<Add exp1>) -> t2
                        t3 = t1 <addop> t2

                Resultado en: t3
                -------------------------------------------------------------------------*/

                t1 = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                t2 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                this.liberarTemporal(t1);
                this.liberarTemporal(t2);

                t3 = this.getTemporal();

                operando = (String)((Reduction)reduction.getToken(1).getData()).getToken(0).getData();

                this.addToCode(new InterOperacionBinaria(t3,t1,operando,t2));

                retorno = t3;

                //this.liberarTemporal(t1);
                //this.liberarTemporal(t2);


                break;
            case DecafParser.RuleConstants.RULE_ADDEXP2:
                //#########################################################################################################
                //<Add Exp> ::= <Mult Exp>
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_MULTEXP:
                //#########################################################################################################
                //<Mult Exp> ::= <Negate Exp> <mulop> <Mult Exp>

                /*-------------------------------------------------------------------------
                <Negate Exp> <mulop> <Mult exp1>
                Código:
                        //* /
                        cod(<Negate Exp>) -> t1
                        cod(<Mult exp1>) -> t2
                        t3 = t1 <mulop> t2

                Resultado en: t3
                -------------------------------------------------------------------------*/

                t1 = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                t2 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                this.liberarTemporal(t1);
                this.liberarTemporal(t2);

                t3 = this.getTemporal();

                operando = (String)((Reduction)reduction.getToken(1).getData()).getToken(0).getData();

                this.addToCode(new InterOperacionBinaria(t3,t1,operando,t2));

                retorno = t3;

                //this.liberarTemporal(t1);
                //this.liberarTemporal(t2);

                break;
            case DecafParser.RuleConstants.RULE_MULTEXP2:
                //#########################################################################################################
                //<Mult Exp> ::= <Negate Exp>
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_NEGATEEXP_MINUS:
                //#########################################################################################################
                //<Negate Exp> ::= '-' <Value>


                /*-------------------------------------------------------------------------
                '-' <Value>
                Código:
                        //cambiar de signo
                        cod(<Value>) -> t1
                        t2 = 0 - t1

                Resultado en: t2
                -------------------------------------------------------------------------*/

                t1 = this.genCodeExpression((Reduction)reduction.getToken(1).getData());

                this.liberarTemporal(t1);

                t2 = this.getTemporal();

                this.addToCode(new InterOperacionBinaria(t2,"0","-",t1));

                retorno = t2;

                //this.liberarTemporal(t1);

                break;
            case DecafParser.RuleConstants.RULE_NEGATEEXP_EXCLAM:
                //#########################################################################################################
                //<Negate Exp> ::= '!' <Value>


                /*-------------------------------------------------------------------------
                '!' <Value>
                Código:
                        //cambiar de 0 a 1
                        cod(<Value>) -> t1
                        if t1 == 0 goto L1
                        t2 = 0
                        goto L2
                L1:
                        t2 = 1
                L2:
                -------------------------------------------------
                 * cod(<Value>) -> t1
                 * t2 = not t1
                 * t2 = 1 and t2
                Resultado en: t2
                -------------------------------------------------------------------------*/
                

                t1 = this.genCodeExpression((Reduction)reduction.getToken(1).getData());

                this.liberarTemporal(t1);

                t2 = this.getTemporal();

                this.addToCode(new InterOperacionUnaria(t2,"not",t1));

                this.addToCode(new InterOperacionBinaria(t2,"1","and",t2));
                
                retorno = t2;

                //this.liberarTemporal(t1);

                break;
            case DecafParser.RuleConstants.RULE_NEGATEEXP:
                //#########################################################################################################
                //<Negate Exp> ::= <Value>
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_VALUE:
                //#########################################################################################################
                //<Value> ::= <literal>
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                break;

            case DecafParser.RuleConstants.RULE_VALUE_LPARAN_RPARAN:
                //#########################################################################################################
                //<Value> ::= '(' <expression> ')'
                retorno = this.genCodeExpression((Reduction)reduction.getToken(1).getData());
                break;
            case DecafParser.RuleConstants.RULE_VALUE2:
                //#########################################################################################################
                //<Value> ::= <methodCall>
                retorno = this.genMethodCall((Reduction)reduction.getToken(0).getData(),"",0);
                break;
            case DecafParser.RuleConstants.RULE_VALUE3:
                //#########################################################################################################
                //<Value> ::= <location>
                
                
                t2 = this.genCodeLocation((Reduction)reduction.getToken(0).getData());

                //this.liberarTemporalLocation(t2);

                t1 = this.getTemporal();

                this.addToCode(new InterAsignacion(t1,t2));

                retorno = t1;



                break;
            case DecafParser.RuleConstants.RULE_LITERAL: case DecafParser.RuleConstants.RULE_LITERAL2:
            case DecafParser.RuleConstants.RULE_LITERAL3:
                //#########################################################################################################
                //<literal> ::= <int_literal>
                //<literal> ::= <char_literal>
                //<literal> ::= <bool_literal>
                
                retorno = this.genCodeExpression((Reduction)reduction.getToken(0).getData());

                break;
            case DecafParser.RuleConstants.RULE_INT_LITERAL_NUM: case DecafParser.RuleConstants.RULE_CHAR_LITERAL_CHARACTER:
                //#########################################################################################################
                //<int_literal> ::= num
                //<char_literal> ::= character
                
                retorno =(String)reduction.getToken(0).getData();

                break;
            case DecafParser.RuleConstants.RULE_BOOL_LITERAL_TRUE:
                //#########################################################################################################
                //<bool_literal> ::= true
                retorno = "1";
                break;
            case DecafParser.RuleConstants.RULE_BOOL_LITERAL_FALSE:
                //#########################################################################################################
                //<bool_literal> ::= false
                retorno = "0";
                break;
        }

        return retorno;
    }

    /*****************************************
     * genCodeLocation
     * @param reduction
     * @return String
     *****************************************/
    private String getDesplLocationStructure(Reduction reduction, LinkedList<decaf.Symbol> members){
        String retorno = "",id,t1,t2;
        int cont=0;
        decaf.Symbol miembro = null;
        switch(reduction.getParentRule().getTableIndex()){

            case DecafParser.RuleConstants.RULE_LOCATION_DOT:
                //#########################################################################################################
                //<location> ::= <simpleLocation> '.' <location>

                Reduction simpleLoc = (Reduction)reduction.getToken(0).getData();
                Reduction location = (Reduction)reduction.getToken(2).getData();

                id = (String)simpleLoc.getToken(0).getData();
                for(decaf.Symbol a : members){

                    if(id.equals(a.getId())){
                        miembro = a;
                        break;
                    }
                    cont+=a.getType().getType_length();
                }

                t1 = this.getDesplLocationStructure(simpleLoc, members);
                t2 = this.getDesplLocationStructure(location, miembro.getType().getMembers());

                String t3 = this.getTemporal();

                this.addToCode(new InterOperacionBinaria(t3,t1,"+",t2));

                retorno = t3;
                
                this.liberarTemporal(t1);
                this.liberarTemporal(t2);

                break;
            case DecafParser.RuleConstants.RULE_LOCATION:
                //#########################################################################################################
                //<location> ::= <simpleLocation>
                retorno = this.getDesplLocationStructure((Reduction)reduction.getToken(0).getData(), members);
                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID_LBRACKET_RBRACKET:
                //#########################################################################################################
                //<simpleLocation> ::= id '[' <expression> ']'

                id = (String)reduction.getToken(0).getData();
                for(decaf.Symbol a : members){

                    if(id.equals(a.getId())){
                        miembro = a;
                        break;
                    }
                    cont+=a.getType().getType_length();
                }


                t1 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                int tam_ind = miembro.getType().getType_length_single();

                t2 = this.getTemporal();

                this.addToCode(new InterOperacionBinaria(t2,t1,"*",tam_ind+""));
                this.addToCode(new InterOperacionBinaria(t2,t2,"+",cont+""));

                retorno = t2;

                this.liberarTemporal(t1);

                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID:
                //########################################################################################################
                //<simpleLocation> ::= id

                id = (String)reduction.getToken(0).getData();

                for(decaf.Symbol a : members){

                    if(id.equals(a.getId())){
                        break;
                    }
                    cont+=a.getType().getType_length();
                }

                retorno = cont+"";

                break;
        }

        return retorno;
    }



    /*****************************************
     * genCodeLocation
     * @param reduction
     * @return String
     *****************************************/
    private String genCodeLocation(Reduction reduction){
        
        String retorno="",id,t1,t2,t3;
        decaf.Symbol simbolo;
        int tam;
        String a[];

        switch(reduction.getParentRule().getTableIndex()){
            case DecafParser.RuleConstants.RULE_LOCATION_DOT:
                //#########################################################################################################
                //<location> ::= <simpleLocation> '.' <location>

                //<simpleLocation> ::= id '[' <expression> ']'
                //<simpleLocation> ::= id
                Reduction simpleLoc = (Reduction)reduction.getToken(0).getData();
                String base, despl_inicial;

                id = (String)simpleLoc.getToken(0).getData();
                simbolo = this.parser.getSymbolTable().getSymbol(id, this.actual_ambit);
                a = this.getDesplazamientoSimple(simbolo,parser,this.scope);

                this.addToCode(new InterComentario(" <location> - structure ",true,'°',30));//°°°°°°

                if(simpleLoc.getParentRule().getTableIndex() == DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID){

                    //<simpleLocation> ::= id
                    //obtener el símbolo
                    //obtener el desplazamiento y la base de ese símbolo
                    //obtener el desplazamiento de la location
                    //sumarlos
                    //devolver base [despl_inicial+despl_loc]

                    base = a[0];
                    despl_inicial = a[1];


                }else{
                    //<simpleLocation> ::= id '[' <expression> ']'

                    base = a[0];
                    
                    t1 = this.genCodeExpression((Reduction)simpleLoc.getToken(2).getData());
                    t2 = this.getTemporal();

                    tam = simbolo.getType().getType_length_single();
                    this.addToCode(new InterOperacionBinaria(t2,tam+"","*",t1));
                    this.addToCode(new InterOperacionBinaria(t2,t2,"+",a[1]));
                    despl_inicial = t2;

                    this.liberarTemporal(t1);

                }

                t1 = this.getDesplLocationStructure((Reduction)reduction.getToken(2).getData(), simbolo.getType().getMembers());

                t3 = this.getTemporal();

                this.addToCode(new InterOperacionBinaria(t3,despl_inicial,"+",t1));

                retorno = base+"["+t3+"]";


                this.liberarTemporal(t1);
                this.liberarTemporal(despl_inicial);
                this.liberarTemporal(t3);

                this.addToCode(new InterComentario("",true,'°',30));//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
                
                break;
            case DecafParser.RuleConstants.RULE_LOCATION:
                //#########################################################################################################
                //<location> ::= <simpleLocation>
                retorno = this.genCodeLocation((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID_LBRACKET_RBRACKET:
                //#########################################################################################################
                //<simpleLocation> ::= id '[' <expression> ']'

                /*-------------------------------------------------------------------------
                <simpleLocation> ::= id '[' <expression> ']'
                Código:
                        cod(<expression>)-> t1
                       t2 = tam_ind * t1
                       t2 = t2 + despl_simbolo
                       base[t2]

                Resultado en: base[t2]
                -------------------------------------------------------------------------*/

                this.addToCode(new InterComentario(" <location> - array ",true,'°',30));//°°°°°°

                id = (String)reduction.getToken(0).getData();
                simbolo = this.parser.getSymbolTable().getSymbol(id, this.actual_ambit);

                a = this.getDesplazamientoSimple(simbolo,parser,this.scope);
                //retorno[0] = base;
                //retorno[1] = despl+"";

                t1 = this.genCodeExpression((Reduction)reduction.getToken(2).getData());

                t2 = this.getTemporal();

                tam = simbolo.getType().getType_length_single();

                this.addToCode(new InterOperacionBinaria(t2,tam+"","*",t1));
                this.addToCode(new InterOperacionBinaria(t2,t2,"+",a[1]));

                retorno = a[0]+"["+t2+"]";

                
                this.liberarTemporal(t1);
                this.liberarTemporal(t2);

                this.addToCode(new InterComentario("",true,'°',30));//°°°°°°°°°°°°°°°°°°°°°°°°°°°

                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID:
                //########################################################################################################
                //<simpleLocation> ::= id
                
                id = (String)reduction.getToken(0).getData();
                simbolo = this.parser.getSymbolTable().getSymbol(id, this.actual_ambit);

                a = this.getDesplazamientoSimple(simbolo,parser,this.scope);
                //retorno[0] = base;
                //retorno[1] = despl+"";
                retorno = a[0]+"["+a[1]+"]";


                break;
        }


        return retorno;
    }

    /*****************************************
     * getDesplazamientoSimple
     * Obtiene la base y el desplazamiento de
     * un símbolo
     * @param Symbol
     * @return String[] de la forma:
     *      retorno[0] = base;
            retorno[1] = despl+"";
     *****************************************/
    public static String[] getDesplazamientoSimple(decaf.Symbol symbol, decaf.DecafParser parser, Scope actual_ambit){

        String base;
        String retorno[] = new String[2];

        int despl = 0;


        //ver si es global
        if(symbol.getScope().getName() == 0){

            base = "global";

            LinkedList<decaf.Symbol> simbGlobal = parser.getSymbolTable().getAllGlobalSymbol(actual_ambit);

            //System.out.println("Simbolos en ambitos hijos: \n"+simbGlobal);

            for(decaf.Symbol a : simbGlobal){

                if(a == symbol){
                    break;
                }else{
                    despl+=a.getType().getType_length();
                }
            }


        }else{
            //está definida en el método actual

            base = "stack";

            LinkedList<decaf.Symbol> simbLocal = parser.getSymbolTable().getAllSymbolInScopeAndKids(actual_ambit);

            //System.out.println("Simbolos en ambitos hijos: \n"+simbLocal);

            for(decaf.Symbol a : simbLocal){

                if(a == symbol){
                    break;
                }else{
                    despl+=a.getType().getType_length();
                }
            }


        }

        retorno[0] = base;
        retorno[1] = despl+"";
        
        return retorno;
    }

    /*****************************************
     * genMethodCall
     * @param reduction
     * @return void
     *****************************************/
    private String genMethodCall(Reduction reduction, String subname, int num){
        
        String retorno = "", t1, signature;
        Method llamado;

        switch(reduction.getParentRule().getTableIndex()){
            case DecafParser.RuleConstants.RULE_METHODCALL_ID_LPARAN_RPARAN:
                //#########################################################################################################
                //<methodCall> ::= id '(' <opt_arg_separated> ')'
                signature = this.getMethodCallSignature(reduction);

                System.out.println("signature: "+signature+"------------------------------");

                llamado = parser.getMethodTable().getMethod(signature);
                //System.out.println("******************************************"+ llamado.getMethodSignature()+"\n"+llamado.getSubname());

                this.addToCode(new InterComentario(" <methodCall> ",true,'+',30));//++++++++++

                if(  llamado.getRet().getType_name().equals("void") ){

                    /*-------------------------------------------------------------------------
                    Si es void el tipo de retorno del método
                    Código:
                            cod(opt_arg_separated)
                            call metodo, cant_param
                    -------------------------------------------------------------------------*/
                    this.genMethodCall((Reduction)reduction.getToken(2).getData(),llamado.getSubname(),1);

                    this.addToCode(new InterMethodCall(llamado.getSubname(),llamado.getParameters().size()+""));

                    this.addToCode(new InterComentario("",true,'+',30));//++++++++++++++++++++++++
                    break;
                }

                /*-------------------------------------------------------------------------
                Si es void el tipo de retorno del método
                Código:
                        cod(opt_arg_separated)
                        t1 = call metodo, cant_param
                        retornar t1
                -------------------------------------------------------------------------*/

                t1 = this.getTemporal();

                this.genMethodCall((Reduction)reduction.getToken(2).getData(),llamado.getSubname(),1);

                this.addToCode(new InterMethodCall(t1,llamado.getSubname(),llamado.getParameters().size()+""));

                retorno = t1;

                this.addToCode(new InterComentario("",true,'+',30));//++++++++++++++++++++++++

                break;
            case DecafParser.RuleConstants.RULE_OPT_ARG_SEPARATED:
                //#########################################################################################################
                //<opt_arg_separated> ::= <arg list>
                this.genMethodCall((Reduction)reduction.getToken(0).getData(),subname,num);
                break;
            case DecafParser.RuleConstants.RULE_OPT_ARG_SEPARATED2:
                //#########################################################################################################
                //<opt_arg_separated> ::=
                break;
            case DecafParser.RuleConstants.RULE_ARGLIST:
                //#########################################################################################################
                //<arg list> ::= <arg>
                this.genMethodCall((Reduction)reduction.getToken(0).getData(),subname,num);
                break;
            case DecafParser.RuleConstants.RULE_ARGLIST_COMMA:
                //#########################################################################################################
                //<arg list> ::= <arg list> ',' <arg>
                this.genMethodCall((Reduction)reduction.getToken(2).getData(),subname,num);
                this.genMethodCall((Reduction)reduction.getToken(0).getData(),subname,num+1);
                break;
            case DecafParser.RuleConstants.RULE_ARG:
                //#########################################################################################################
                //<arg> ::= <expression>
                t1 = this.genCodeExpression((Reduction)reduction.getToken(0).getData());
                this.addToCode(new InterParam(t1,subname,num));

                this.liberarTemporal(t1);

                break;
        }
        return retorno;
    }



    /***************************************************************
    * getMethodCallSignature
    * @param reduction
    * @return void
    ***************************************************************/
    private String getMethodCallSignature(Reduction reduction) {
        //<methodCall> ::= id '(' <opt_arg_separated> ')'
        String signature = "";
        LinkedList<String> parameters = this.getActualParameters((Reduction)reduction.getToken(2).getData());
        String id = (String)reduction.getToken(0).getData();

        signature = id+"(";
        if(parameters.size()>0){
            signature+=parameters.get(0)+",";
            for(int i = 1;i<parameters.size(); i++){
                String a  = parameters.get(i);
                signature+=""+a+",";
            }
            signature = signature.substring(0, signature.length()-1);
        }
        signature+=")";

        return signature;
    }

    /***************************************************************
    * getActualParameters
    * @param reduction
    * @return void
    ***************************************************************/
    private LinkedList<String> getActualParameters(Reduction reduction) {
        //<methodCall> ::= id '(' <opt_arg_separated> ')'
        LinkedList<String> actual_param = new LinkedList<String>();

        switch(reduction.getParentRule().getTableIndex())
        {
            case DecafParser.RuleConstants.RULE_OPT_ARG_SEPARATED:
                //#########################################################################################################
                //<opt_arg_separated> ::= <arg list>
                actual_param.addAll(this.getActualParameters((Reduction)reduction.getToken(0).getData()));
                break;
            case DecafParser.RuleConstants.RULE_OPT_ARG_SEPARATED2:
                //#########################################################################################################
                //<opt_arg_separated> ::=
                break;
            case DecafParser.RuleConstants.RULE_ARGLIST:
                //#########################################################################################################
                //<arg list> ::= <arg>
                actual_param.addAll(this.getActualParameters((Reduction)reduction.getToken(0).getData()));
                break;
            case DecafParser.RuleConstants.RULE_ARGLIST_COMMA:
                //#########################################################################################################
                //<arg list> ::= <arg list> ',' <arg>
                actual_param.addAll(this.getActualParameters((Reduction)reduction.getToken(0).getData()));
                actual_param.addAll(this.getActualParameters((Reduction)reduction.getToken(2).getData()));
                break;
            case DecafParser.RuleConstants.RULE_ARG:
                //#########################################################################################################
                //<arg> ::= <expression>
                String arg = this.obtainType((Reduction)reduction.getToken(0).getData());
                actual_param.add(arg);
                break;
        }
        return actual_param;
    }

    /***************************************************************
    * obtainType
    * recursive method to check the type
    * @param reduction
    ***************************************************************/
    private String obtainType(Reduction reduction){
        String retorno = "";

        String Rel_Exp, expression, Add_Exp, Mult_Exp, Negate_Exp, Value, simpleLocation;
        decaf.Symbol symbol;

        switch(reduction.getParentRule().getTableIndex())
        {
            case DecafParser.RuleConstants.RULE_EXPRESSION:
                //#########################################################################################################
                //<expression> ::= <Rel Exp> <conditionalop> <expression>

                retorno = "boolean";

                break;
            case DecafParser.RuleConstants.RULE_EXPRESSION2:
                //#########################################################################################################
                //<expression> ::= <Rel Exp>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_RELEXP:
                //#########################################################################################################
                //<Rel Exp> ::= <Add Exp> <relop> <Rel Exp>
                //<relop> ::= '<=' | '<' | '>' | '>=' | '==' | '!='
                retorno = "boolean";
                break;
            case DecafParser.RuleConstants.RULE_RELEXP2:
                //#########################################################################################################
                //<Rel Exp> ::= <Add Exp>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_ADDEXP:
                //#########################################################################################################
                //<Add Exp> ::= <Mult Exp> <addop> <Add Exp>
                retorno = "int";
                break;
            case DecafParser.RuleConstants.RULE_ADDEXP2:
                //#########################################################################################################
                //<Add Exp> ::= <Mult Exp>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_MULTEXP:
                //#########################################################################################################
                //<Mult Exp> ::= <Negate Exp> <mulop> <Mult Exp>
                retorno = "int";
                break;
            case DecafParser.RuleConstants.RULE_MULTEXP2:
                //#########################################################################################################
                //<Mult Exp> ::= <Negate Exp>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_NEGATEEXP_MINUS:
                //#########################################################################################################
                //<Negate Exp> ::= '-' <Value>
                retorno = "int";
                break;
            case DecafParser.RuleConstants.RULE_NEGATEEXP_EXCLAM:
                //#########################################################################################################
                //<Negate Exp> ::= '!' <Value>
                retorno = "boolean";
                break;
            case DecafParser.RuleConstants.RULE_NEGATEEXP:
                //#########################################################################################################
                //<Negate Exp> ::= <Value>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_VALUE:
                //#########################################################################################################
                //<Value> ::= <literal>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_VALUE_LPARAN_RPARAN:
                //#########################################################################################################
                //<Value> ::= '(' <expression> ')'
                retorno = this.obtainType((Reduction)reduction.getToken(1).getData());
                break;
            case DecafParser.RuleConstants.RULE_VALUE2:
                //#########################################################################################################
                //<Value> ::= <methodCall>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_VALUE3:
                //#########################################################################################################
                //<Value> ::= <location>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_LOCATION_DOT:
                //*********************************************************************************************************
                //<location> ::= <simpleLocation> '.' <location>

                //obtener a simpleLocation
                simpleLocation = this.obtainType((Reduction)reduction.getToken(0).getData());

                if(simpleLocation.equals("error")){
                    retorno = "error";
                    break;
                }

                String id_location_1 = (String)((Reduction)reduction.getToken(0).getData()).getToken(0).getData();

                //revisar si es un struct (empieza con "struct:")
                if(!simpleLocation.startsWith("struct:")){
                    retorno = "error";
                    break;
                }

                if(simpleLocation.endsWith("[]")){
                    retorno = "error";
                    break;
                }

                //buscarlo en la tabla de símbolos
                symbol = this.parser.getSymbolTable().getSymbol(id_location_1, actual_ambit);
                retorno = this.getTypeLocation((Reduction)reduction.getToken(2).getData(), symbol.getType().getMembers());
                break;
            case DecafParser.RuleConstants.RULE_LOCATION:
                //*********************************************************************************************************
                //<location> ::= <simpleLocation>
                retorno = this.obtainType((Reduction)reduction.getToken(0).getData());
                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID_LBRACKET_RBRACKET:
                //*********************************************************************************************************
                //<simpleLocation> ::= id '[' <expression> ']'

                //primero revisar que <expression> sea de tipo int
                expression = this.obtainType((Reduction)reduction.getToken(2).getData());

                if(expression.equals("error")){
                    retorno = "error";
                    break;
                }else if(!expression.equals("int")){
                    retorno = "error";
                    System.out.println("tipo incompatible.... [!int]");
                    //break;//TODO ver si es necesario ponerlo...
                }

                String id_simpleLocation_2 = (String)reduction.getToken(0).getData();
                symbol = this.parser.getSymbolTable().getSymbol(id_simpleLocation_2, actual_ambit);
                if(symbol == null){
                    //no encontró en la tabla de símbolos
                    //cannot find symbol (Line 2): a
                    retorno = "error";
                }else{
                    //revisar si el símbolo es un arreglo.. si es quitar el final "[]" si no es -> error
                    if(symbol.getType().isArray()){
                        retorno = symbol.getType().getType_name().substring(0, symbol.getType().getType_name().length()-2);
                    }else{
                        retorno = "error";
                    }
                }

                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID:
                //*********************************************************************************************************
                //<simpleLocation> ::= id

                String id_simpleLocation_1 = (String)reduction.getToken(0).getData();
                symbol = this.parser.getSymbolTable().getSymbol(id_simpleLocation_1, actual_ambit);
                if(symbol == null){
                    //no encontró en la tabla de símbolos
                    //cannot find symbol (Line 2): a
                    retorno = "error";
                }else{
                    retorno = symbol.getType().getType_name();
                }

                break;
            case DecafParser.RuleConstants.RULE_METHODCALL_ID_LPARAN_RPARAN:
                //#########################################################################################################
                //<methodCall> ::= id '(' <opt_arg_separated> ')'

                //obtener la firma de esta llamada a método y buscarla en la tabla de métodos
                String signature = getMethodCallSignature(reduction);
                //por si los argumentos ya tienen un error...
                if(signature.contains("error") && !signature.startsWith("error")){
                    retorno = "error";
                    break;
                }

                Method correct_method = this.parser.getMethodTable().getMethod(signature);
                if(correct_method!=null && !signature.isEmpty()){
                    retorno = correct_method.getRet().getType_name();
                }else{
                    //cannot find symbol method (Line 2): method(boolean,int)
                    retorno = "error";
                }

                break;
            case DecafParser.RuleConstants.RULE_LITERAL:
                //#########################################################################################################
                //<literal> ::= <int_literal>//<int_literal> ::= num
                retorno = "int";
                break;
            case DecafParser.RuleConstants.RULE_LITERAL2:
                //#########################################################################################################
                //<literal> ::= <char_literal>//<char_literal> ::= character
                retorno = "char";
                break;
            case DecafParser.RuleConstants.RULE_LITERAL3:
                //#########################################################################################################
                //<literal> ::= <bool_literal>//<bool_literal> ::= true | false
                retorno = "boolean";
                break;
        }
        return retorno;
    }

    /*****************************************
     * getTypeLocation
     * @return String with the type
     * @param reduction
     * @param members
     *****************************************/
    private String getTypeLocation(Reduction reduction, LinkedList<decaf.Symbol> members){
        String retorno = "";

        switch(reduction.getParentRule().getTableIndex())
        {
            case DecafParser.RuleConstants.RULE_LOCATION_DOT:
                //---------------------------------------------------------------------------------------------------------
                //<location> ::= <simpleLocation> '.' <location>

                String simpleLocation = this.getTypeLocation((Reduction)reduction.getToken(0).getData(), members);

                if(simpleLocation.equals("error")){
                    retorno = "error";
                    break;
                }

                String id_location_1 = (String)((Reduction)reduction.getToken(0).getData()).getToken(0).getData();

                //revisar si es un struct (empieza con "struct:")
                if(!simpleLocation.startsWith("struct:")){
                    retorno = "error";
                    break;
                }

                if(simpleLocation.endsWith("[]")){
                    retorno = "error";
                    break;
                }

                //buscarlo entre los miembros
                decaf.Symbol symbol_0 = this.getLocation_in_Member(id_location_1, members);
                retorno = this.getTypeLocation((Reduction)reduction.getToken(2).getData(), symbol_0.getType().getMembers());
                break;
            case DecafParser.RuleConstants.RULE_LOCATION:
                //---------------------------------------------------------------------------------------------------------
                //<location> ::= <simpleLocation>
                retorno = this.getTypeLocation((Reduction)reduction.getToken(0).getData(), members);
                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID_LBRACKET_RBRACKET:
                //---------------------------------------------------------------------------------------------------------
                //<simpleLocation> ::= id '[' <expression> ']'

                String expression = this.obtainType((Reduction)reduction.getToken(2).getData());
                String id_2 = (String)reduction.getToken(0).getData();
                decaf.Symbol symbol_2 = this.getLocation_in_Member(id_2, members);
                if(symbol_2.getType().isArray()){
                    //quitar el "[]" del final...
                    retorno = symbol_2.getType().getType_name().substring(0, symbol_2.getType().getType_name().length()-2);
                }

                break;
            case DecafParser.RuleConstants.RULE_SIMPLELOCATION_ID:
                //---------------------------------------------------------------------------------------------------------
                //<simpleLocation> ::= id
                String id = (String)reduction.getToken(0).getData();
                decaf.Symbol symbol = this.getLocation_in_Member(id, members);
                retorno = symbol.getType().getType_name();
                break;
        }


        return retorno;
    }

    /***************************************************************
    * existLocation_in_Member
    * @param location
    * @param members
    * @return boolean
    ***************************************************************/
    private decaf.Symbol getLocation_in_Member(String location, LinkedList<decaf.Symbol> members) {

        for(decaf.Symbol a : members){
            if(location.equals(a.getId())){
                return a;
            }
        }

        return null;
    }

}
